package com.hlw.springboot.config;


import com.hlw.springboot.entity.SysPermission;
import com.hlw.springboot.entity.SysRole;
import com.hlw.springboot.entity.SysUser;
import com.hlw.springboot.mapper.SysPermissionMapper;
import com.hlw.springboot.mapper.SysRoleMapper;
import com.hlw.springboot.mapper.SysUserMapper;
import com.hlw.springboot.service.SysRoleService;
import com.hlw.springboot.service.SysUserService;
import com.hlw.springboot.util.SpringUtil;
import com.hlw.springboot.util.UserUtil;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class ShiroRealm extends AuthorizingRealm {

    private Logger logger = LoggerFactory.getLogger(ShiroRealm.class);


    @Autowired
    private SysUserService userInfoService;

    @Autowired
    private SysRoleService sysRoleService;

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private SysRoleMapper sysRoleMapper;

    @Resource
    private SysPermissionMapper sysPermissionMapper;


    /**
     * 登录认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        logger.info("验证当前Subject时获取到token为：" + token.toString());
        //查出是否有此用户
        String username = token.getUsername();
        SysUser hasUser = sysUserMapper.findByName(username);
        System.out.println("拿到当前的用户信息为："+hasUser);
        if (hasUser != null) {
            if(hasUser.getStatus()==0){
                throw new LockedAccountException();

            }else{
                // 若存在，将此用户存放到登录认证info中，无需自己做密码对比，Shiro会为我们进行密码对比校验
                Integer rid = sysRoleMapper.findRoleByUid(hasUser.getId());//获取用户角色
                SysRole role =sysRoleMapper.selectByPrimaryKey(rid);
                List<SysPermission> plist = sysPermissionMapper.findPermissionByRoleId(hasUser.getId());//获取用户权限
                List<String> roleStrlist=new ArrayList<String>();////用户的角色集合
                List<String> perminsStrlist=new ArrayList<String>();//用户的权限集合

                roleStrlist.add(role.getName());

                for (SysPermission uPermission : plist) {
                    perminsStrlist.add(uPermission.getName());
                }
                hasUser.setRoleStrlist(roleStrlist);
                hasUser.setPerminsStrlist(perminsStrlist);
                // 若存在，将此用户存放到登录认证info中，无需自己做密码对比，Shiro会为我们进行密码对比校验
                return new SimpleAuthenticationInfo(hasUser, hasUser.getPassword(), ByteSource.Util.bytes(hasUser.getSalt()), getName());
            }
        }

        return null;
    }

    /**
     * 权限认证
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        logger.info("##################执行Shiro权限认证##################");
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        SysUser user = (SysUser) principalCollection.getPrimaryPrincipal();
        if (user != null) {
            List<SysRole> roles = SpringUtil.getBean(SysRoleMapper.class).listByUserId(user.getId());
            Set<String> roleNames = roles.stream().map(SysRole::getName).collect(Collectors.toSet());
            authorizationInfo.setRoles(roleNames);
            List<SysPermission> permissionList = SpringUtil.getBean(SysPermissionMapper.class).listByUserId(user.getId());
            UserUtil.setPermissionSession(permissionList);
            Set<String> permissions = permissionList.stream().filter(p -> !StringUtils.hasLength(p.getPermission()))
                    .map(SysPermission::getPermission).collect(Collectors.toSet());
            authorizationInfo.setStringPermissions(permissions);

            return authorizationInfo;
        }
        // 返回null的话，就会导致任何用户访问被拦截的请求时，都会自动跳转到unauthorizedUrl指定的地址
        return null;
    }

}